#include "buffer.h"

net_tcp::buffer::buffer(int cache_size)
{
	m_data = nullptr;
	resize(cache_size);
}

net_tcp::buffer::~buffer()
{
	if (m_data != nullptr) {
		free(m_data);
	}
}

void net_tcp::buffer::shrink()
{
	int datasize = m_write_pos - m_read_pos;
	memmove_s(m_data, m_data_size, m_data + m_read_pos, datasize);
	m_read_pos = 0;
	m_write_pos = datasize;
}

bool net_tcp::buffer::resize(int cache_size)
{
	if (cache_size <= 0) return false;

	char* newdata = (char*)malloc(cache_size);
	if (m_data != nullptr) {
		int datasize = m_write_pos - m_read_pos;
		if (datasize > cache_size) {
			cache_size = datasize;
		}
		if (newdata != nullptr) {
			memcpy(newdata, m_data + m_read_pos, datasize);
		}
		free(m_data);
	}
	m_data = newdata;
	m_data_size = cache_size;
	m_read_pos = m_write_pos = 0;
	return true;
}

bool net_tcp::buffer::prepare_write(int data_size)
{
	if (writeable_size() >= data_size)
	{
		return true;
	}

	if (writeable_size() + m_read_pos >= data_size)
	{
		shrink();
		return true;
	}

	return resize(data_size + m_data_size);
}

int net_tcp::buffer::readable_size()
{
	return m_write_pos - m_read_pos;
}

int net_tcp::buffer::writeable_size()
{
	return m_data_size - m_write_pos;
}

char* net_tcp::buffer::read_pointer()
{
	std::cout << "m_read_pos:" << m_read_pos << std::endl;
	std::cout << "m_write_pos:" << m_write_pos << std::endl;
	return m_data + m_read_pos;
}

char* net_tcp::buffer::write_pointer()
{
	return m_data + m_write_pos;
}

void net_tcp::buffer::increase_read(int len)
{
	m_read_pos += len;
	m_read_pos = std::clamp(m_read_pos, 0, m_data_size);
}

void net_tcp::buffer::increase_write(int len)
{
	m_write_pos += len;
	m_write_pos = std::clamp(m_write_pos, 0, m_data_size);
}

bool net_tcp::buffer::write(const char* data, int len)
{
	if (prepare_write(len))
	{
		memcpy_s(m_data + m_write_pos, len, data, len);
		m_write_pos += len;
		return true;
	}
	return false;
}

bool net_tcp::buffer::read(char* data, int len)
{
	if (readable_size() > len)
	{
		memcpy_s(data, len, m_data + m_read_pos, len);
		m_read_pos += len;
	}
	return false;
}
